﻿using EzDesk.Apps.Model.Attendance;
using NUnit.Framework;

namespace EzDesk.Apps.UnitTest.Attendance
{
    [TestFixture]
    public class DayAttendanceEvaluationFixture
    {
        #region [ private methods ]
        
        private void assertEvaluation(
            DayAttendanceEvaluation actualResult,
            bool isNeedToWork,
            int lateMiniutes,
            int earlyMiniutes,
            bool isAbsense,
            bool isExtrawork,
            int manHours,
            string status = "normal")
        {
            Assert.AreEqual(isNeedToWork, actualResult.IsNeedToWork);
            Assert.AreEqual(lateMiniutes, actualResult.LateMiniutes);
            Assert.AreEqual(earlyMiniutes, actualResult.EarlyMiniutes);
            Assert.AreEqual(isAbsense, actualResult.IsAbsense);
            Assert.AreEqual(isExtrawork, actualResult.IsExtraWork);
            Assert.AreEqual(manHours, actualResult.Manhours.ToManhours());
            Assert.AreEqual(status, actualResult.Status);
        }

        #endregion


        #region [ Test Methods ]


        [Test]
        public void Test_正常情况()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")
                .SetupAttendanceInfo("8:40", "onDuty", false)
                .SetupAttendanceInfo("19:00", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }

        [Test]
        public void Test_正常情况_1()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-07-22")
                .SetupAttendanceInfo("9:00:03", "onDuty", false)
                .SetupAttendanceInfo("18:02:02", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }

        [Test]
        public void Test_早退一分钟()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-07-22")
                .SetupAttendanceInfo("9:00:03", "onDuty", false)
                .SetupAttendanceInfo("17:59:40", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 1, false, false, 75);
        }

        [Test]
        public void Test_迟到几秒钟()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-07-22")
                .SetupAttendanceInfo("9:05:40", "onDuty", false)
                .SetupAttendanceInfo("18:00:00", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 6, 0, false, false, 75);
        }

        [Test]
        public void Test_早上迟到下午正常下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("10:20", "onDuty", false)
                .SetupAttendanceInfo("18:00", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 80, 0, false, false, 65);
        }
        
        [Test]
        public void Test_早上迟到下午晚下班_加班后工时应该不算_倒扣迟到工时()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("9:20", "onDuty", false)
                .SetupAttendanceInfo("19:20", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 20, 0, false, false, 75);
        }


        [Test]
        public void Test_早上正常上班下午早退()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("8:50", "onDuty", false)
                .SetupAttendanceInfo("16:40", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 70, false, false, 65);
        }


        [Test]
        public void Test_早上正常上班下午没打卡()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("8:50", "onDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 0);
        }


        [Test]
        public void Test_早上迟到下午没打卡()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("10:50", "onDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 110, 0, false, false, 0);
        }


        [Test]
        public void Test_早上没打卡下午打了下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("19:50", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 0);
        }


        [Test]
        public void Test_中午过来上班晚上正常下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("12:10", "onDuty", true)
                .SetupAttendanceInfo("19:10", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 190, 0, false, false, 55);
        }




        [Test]
        public void Test_昨晚通宵到今天正常上班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("2:20", "offDuty", true)
                .SetupAttendanceInfo("9:00", "onDuty", false)
                .SetupAttendanceInfo("19:00", "offDuty", false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }

        [Test]
        public void Test_昨晚通宵到今天早上下班_下午过来上班晚上下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("3:20", "offDuty", true)
                .SetupAttendanceInfo("14:00", "onDuty", true)
                .SetupAttendanceInfo("20:50", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 300, 0, false, false, 40);
        }

        [Test]
        public void Test_连续几次非正常上下班_按最少的计算()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("3:20", "onDuty", true)
                .SetupAttendanceInfo("4:20", "onDuty", true)
                .SetupAttendanceInfo("5:20", "onDuty", true)

                .SetupAttendanceInfo("7:20", "offDuty", true)
                .SetupAttendanceInfo("8:20", "offDuty", true)


                .SetupAttendanceInfo("17:20", "onDuty", true)
                .SetupAttendanceInfo("20:20", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 0, "normal");
        }

        [Test]
        public void Test_周末上班不算迟到()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-9")

                .SetupAttendanceInfo("10:20", "onDuty", true)
                .SetupAttendanceInfo("20:20", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, false, 0, 0, false, true, 80, "notwork");
        }

        [Test]
        public void Test_昨天十点今天可以晚到一个小时()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-7")

                .SetupAttendanceInfo("8:20", "onDuty", true)
                .SetupAttendanceInfo("22:20", "offDuty", true)
                .SetupDay("2011-7-8")
                .SetupAttendanceInfo("9:40", "onDuty", true)
                .SetupAttendanceInfo("19:40", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);

        }

        [Test]
        public void Test_昨天十点今天了晚到一个小时_实际工时不到8小时()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-7")

                .SetupAttendanceInfo("8:20", "onDuty", true)
                .SetupAttendanceInfo("22:20", "offDuty", true)
                .SetupDay("2011-7-8")
                .SetupAttendanceInfo("9:58", "onDuty", true)
                .SetupAttendanceInfo("18:01", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }
        [Test]
        public void Test_昨天十点今天正常()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-7")

                .SetupAttendanceInfo("8:20", "onDuty", true)
                .SetupAttendanceInfo("22:20", "offDuty", true)
                .SetupDay("2011-7-8")
                .SetupAttendanceInfo("8:50", "onDuty", true)
                .SetupAttendanceInfo("18:01", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }

        [Test]
        public void Test_昨天十点今天迟到两小时()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-7")

                .SetupAttendanceInfo("8:20", "onDuty", true)
                .SetupAttendanceInfo("22:20", "offDuty", true)
                .SetupDay("2011-7-8")
                .SetupAttendanceInfo("10:50", "onDuty", true)
                .SetupAttendanceInfo("18:01", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 50, 0, false, false, 70);
        }

        [Test]
        public void Test_昨天十点正好下班_今天边界正常()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2011-7-7")

                .SetupAttendanceInfo("8:20", "onDuty", true)
                .SetupAttendanceInfo("22:00", "offDuty", true)
                .SetupDay("2011-7-8")
                .SetupAttendanceInfo("10:00", "onDuty", true)
                .SetupAttendanceInfo("18:00", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80);
        }


        #region [ 有假期的情况 ]

        [Test]
        public void Test_上午工作请假下午来上班晚上下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 14:00", false, true)
                .SetupAttendanceInfo("14:00", "onDuty", true)
                .SetupAttendanceInfo("18:50", "offDuty", true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80, "leave");
        }

        [Test]
        public void Test_全天工作假期()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 19:00", true, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80, "leave");
        }

        [Test]
        public void Test_上午正常上班下午非工作假期提前下班()
        {
            var context = new DayAttendanceEvaluationContext()
               .SetupDay("2010-11-12")

               .SetupAttendanceInfo("9:00", "onDuty", false)
               .SetupAttendanceInfo("16:00", "offDuty", false)

               .SetupDayLeaveInfo("事假", "2010-11-12 16:00", "2010-11-12 19:00", false, false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 60, "leave");
        }

        [Test]
        public void Test_上午上班迟到下午非工作假期提前下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("11:00", "onDuty", false)
                .SetupAttendanceInfo("16:00", "offDuty", false)
                .SetupDayLeaveInfo("事假", "2010-11-12 16:00", "2010-11-12 19:00", false, false);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 120, 0, false, false, 40, "leave");
        }

        [Test]
        public void Test_上午正常上班下午工作假期提前下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("9:00", "onDuty", false)
                .SetupAttendanceInfo("16:00", "offDuty", false)
                .SetupDayLeaveInfo("出差", "2010-11-12 16:00", "2010-11-12 19:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80, "leave");
        }

        [Test]
        public void Test_上午上班迟到下午工作假期提前下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("11:00", "onDuty", false)
                .SetupAttendanceInfo("16:00", "offDuty", false)
                .SetupDayLeaveInfo("出差", "2010-11-12 16:00", "2010-11-12 19:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 120, 0, false, false, 70, "leave");
        }


        [Test]
        public void Test_上午工作假期下午上班正常下班()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("15:00", "onDuty", true)
                .SetupAttendanceInfo("18:00", "offDuty", true)
                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 15:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 80, "leave");
        }

        [Test]
        public void Test_上午工作假期下午上班下班忘记打卡()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("15:00", "onDuty", true)
                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 15:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 60, "leave");
        }

        [Test]
        public void Test_上午工作假期下午忘记上班打卡_下班打卡()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")

                .SetupAttendanceInfo("19:00", "offDuty", true)
                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 15:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 50, "leave");
        }

        [Test]
        public void Test_上午工作假期下午上下班忘记打卡()
        {
            var context = new DayAttendanceEvaluationContext()
                .SetupDay("2010-11-12")
                .SetupDayLeaveInfo("出差", "2010-11-12 9:00", "2010-11-12 16:00", false, true);

            var actualResult = context.Service.GetAttendanceEvaluation();

            assertEvaluation(actualResult, true, 0, 0, false, false, 70, "leave");
        }

        #endregion



        #endregion
    }
}